import os
import logging
import inspect

onnx_path = "encoder_shapeinfer.onnx"
fused_onnx = "encoder_shapeinfer_fusednoGLU.onnx"
static_onnx = "encoder_shapeinfer_fusednoGLU_static.onnx"
inputmask_onnx = "encoder_shapeinfer_fusednoGLU_static_inputmask.onnx"
const_onnx = "encoder_shapeinfer_fusednoGLU_static_inputmask_const.onnx"


# logging.basicConfig(level=logging.INFO)
class Logger:
    def __init__(self):        
        pass
    
    def level_str_to_log(self, level):
        log_str = ["debug", "info", "warning", "error"]
        log_level = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR]
        
        level_input = level.lower()
        for n, m in enumerate(log_str):
            if level_input == m: 
                level=log_level[n]
        return level
    
    def set_level(self, level="debug", log_file = "encoder_onnx_modification.log", name = "", std=True, to_file=True):
        # if os.path.exists(log_file):
        #     pid = os.getpid()
        #     with open(log_file) as lf:
        #         content = lf.read()
        #     if str(pid) in content:
        #         os.remove(log_file)
        
        level = self.level_str_to_log(level)
        
        logger_inst = logging.getLogger(name)
        logger_inst = logger_inst
        logger_inst.setLevel(level=level)
        
        fmt = '%(asctime)s - %(name)s - %(levelname)s - %(message)s - pid:%(process)s'
        
        if not logger_inst.handlers:
            # 输出的日志信息格式            
            formatter = logging.Formatter(fmt) 
            ## add file handler
            # 追加写入文件a ，设置utf-8编码防止中文写入乱码
            log_handler = logging.FileHandler(log_file, "a", encoding='utf-8')
            log_handler.setLevel(level=level)
            log_handler.setFormatter(formatter)
            ## add console handler
            console_handler = logging.StreamHandler()
            console_handler.setLevel(level=level)
            console_handler.setFormatter(formatter)
            
            # 加载文件到logger对象中
            if to_file:
                logger_inst.addHandler(log_handler)
            if std:
                logger_inst.addHandler(console_handler)
            
            if not std or not to_file:
                msg = "WARNING: No log will be printed in screen or saved to file"
                print("\033[41;37m {} \033[0m".format(msg))
                logger_inst = None
            
            self.level = level
            self.logger_inst = logger_inst
    
    def log(self, msg, level="debug"):
        # self.set_level(level=level, log_file = log_file)
        if self.logger_inst is not None:
            level = self.level_str_to_log(level)        
            if level== logging.DEBUG:
                self.logger_inst.debug(msg)
            if level== logging.INFO:
                self.logger_inst.info(msg)
            if level== logging.WARNING:
                self.logger_inst.warning(msg)        
            if level== logging.ERROR:
                self.logger_inst.error(msg)

logger = Logger()
level="debug"
msg_fmt = "line:{} - {} - {}"


class LineMeta(type):
    def __repr__(self):
        # Inspiration: https://stackoverflow.com/a/6811020
        callerframerecord = inspect.stack()[1]  # 0 represents this line
        # 1 represents line at caller
        frame = callerframerecord[0]
        info = inspect.getframeinfo(frame)

        # return str(info.lineno)
        
        line = str(info.lineno)
        if len(line) < 4: 
            linespace = " "*(4-len(line))
            line += linespace        
        
        return line

class __LINE__(metaclass=LineMeta):
    pass

class FuncMeta(type):
    def __repr__(self):
        # Inspiration: https://stackoverflow.com/a/6811020
        callerframerecord = inspect.stack()[1]  # 0 represents this line
        # 1 represents line at caller
        frame = callerframerecord[0]
        info = inspect.getframeinfo(frame)
        # print(info.filename)  # __FILE__     -> Test.py
        # print(info.function)  # __FUNCTION__ -> Main
        # print(info.lineno)  # __LINE__     -> 13
        # return str(info.function)
        func = str(info.function)
        if len(func) < 20: 
            funcspace = " "*(20-len(func))
            func += funcspace        
        
        return func

class __FUNC__(metaclass=FuncMeta):
    pass
